/*
 * Copyright (c) 2004-2007 Derelict Developers
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the names 'Derelict', 'DerelictGLC', nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
module derelict.opengl.glc;

private
{
    import derelict.opengl.gltypes;
    import derelict.util.loader;
}

private void load(SharedLib lib)
{
	version(Windows)
	{
		bindFunc(glcContext)("_glcContext@4", lib);
		bindFunc(glcDeleteContext)("_glcDeleteContext@4", lib);
		bindFunc(glcGenContext)("_glcGenContext@0", lib);
		bindFunc(glcGetAllContexts)("_glcGetAllContexts@0", lib);
		bindFunc(glcGetCurrentContext)("_glcGetCurrentContext@0", lib);
		bindFunc(glcGetError)("_glcGetError@0", lib);
		bindFunc(glcIsContext)("_glcIsContext@4", lib);		bindFunc(glcCallbackFunc)("_glcCallbackFunc@8", lib);
		bindFunc(glcDataPointer)("_glcDataPointer@4", lib);
		bindFunc(glcDeleteGLObjects)("_glcDeleteGLObjects@0", lib);
		bindFunc(glcDisable)("_glcDisable@4", lib);
		bindFunc(glcEnable)("_glcEnable@4", lib);
		bindFunc(glcGetCallbackFunc)("_glcGetCallbackFunc@4", lib);
		bindFunc(glcGetListc)("_glcGetListc@8", lib);
		bindFunc(glcGetListi)("_glcGetListi@8", lib);
		bindFunc(glcGetPointer)("_glcGetPointer@4", lib);
		bindFunc(glcGetc)("_glcGetc@4", lib);
		bindFunc(glcGetf)("_glcGetf@4", lib);
		bindFunc(glcGetfv)("_glcGetfv@8", lib);
		bindFunc(glcGeti)("_glcGeti@4", lib);
		bindFunc(glcIsEnabled)("_glcIsEnabled@4", lib);
		bindFunc(glcStringType)("_glcStringType@4", lib);
		bindFunc(glcAppendCatalog)("_glcAppendCatalog@4", lib);		bindFunc(glcGetMasterListc)("_glcGetMasterListc@12", lib);
		bindFunc(glcGetMasterMap)("_glcGetMasterMap@8", lib);
		bindFunc(glcGetMasterc)("_glcGetMasterc@8", lib);
		bindFunc(glcGetMasteri)("_glcGetMasteri@8", lib);
		bindFunc(glcPrependCatalog)("_glcPrependCatalog@4", lib);
		bindFunc(glcRemoveCatalog)("_glcRemoveCatalog@4", lib);		bindFunc(glcAppendFont)("_glcAppendFont@4", lib);
		bindFunc(glcDeleteFont)("_glcDeleteFont@4", lib);
		bindFunc(glcFont)("_glcFont@4", lib);
		bindFunc(glcFontFace)("_glcFontFace@8", lib);
		bindFunc(glcFontMap)("_glcFontMap@12", lib);
		bindFunc(glcGenFontID)("_glcGenFontID@0", lib);
		bindFunc(glcGetFontFace)("_glcGetFontFace@4", lib);
		bindFunc(glcGetFontListc)("_glcGetFontListc@12", lib);
		bindFunc(glcGetFontMap)("_glcGetFontMap@8", lib);
		bindFunc(glcGetFontc)("_glcGetFontc@8", lib);
		bindFunc(glcGetFonti)("_glcGetFonti@8", lib);
		bindFunc(glcIsFont)("_glcIsFont@4", lib);
		bindFunc(glcNewFontFromFamily)("_glcNewFontFromFamily@8", lib);
		bindFunc(glcNewFontFromMaster)("_glcNewFontFromMaster@8", lib);
		bindFunc(glcLoadIdentity)("_glcLoadIdentity@0", lib);
		bindFunc(glcLoadMatrix)("_glcLoadMatrix@4", lib);
		bindFunc(glcMultMatrix)("_glcMultMatrix@4", lib);
		bindFunc(glcRotate)("_glcRotate@4", lib);
		bindFunc(glcScale)("_glcScale@8", lib);
		bindFunc(glcRenderChar)("_glcRenderChar@4", lib);
		bindFunc(glcRenderCountedString)("_glcRenderCountedString@8", lib);
		bindFunc(glcRenderString)("_glcRenderString@4", lib);
		bindFunc(glcRenderStyle)("_glcRenderStyle@4", lib);
		bindFunc(glcReplacementCode)("_glcReplacementCode@4", lib);
		bindFunc(glcResolution)("_glcResolution@4", lib);
		bindFunc(glcGetCharMetric)("_glcGetCharMetric@12", lib);
		bindFunc(glcGetMaxCharMetric)("_glcGetMaxCharMetric@8", lib);
		bindFunc(glcGetStringCharMetric)("_glcGetStringCharMetric@12", lib);
		bindFunc(glcGetStringMetric)("_glcGetStringMetric@8", lib);
		bindFunc(glcMeasureCountedString)("_glcMeasureCountedString@12", lib);
		bindFunc(glcMeasureString)("_glcMeasureString@8", lib);
		bindFunc(glcPushMatrixQSO)("_glcPushMatrixQSO@0", lib);
		bindFunc(glcPopMatrixQSO)("_glcPopMatrixQSO@0", lib);
		bindFunc(glcPushAttribQSO)("_glcPushAttribQSO@4", lib);
		bindFunc(glcPopAttribQSO)("_glcPopAttribQSO@0", lib);
	}
	else
	{
		bindFunc(glcContext)("glcContext", lib);
		bindFunc(glcDeleteContext)("glcDeleteContext", lib);
		bindFunc(glcGenContext)("glcGenContext", lib);
		bindFunc(glcGetAllContexts)("glcGetAllContexts", lib);
		bindFunc(glcGetCurrentContext)("glcGetCurrentContext", lib);
		bindFunc(glcGetError)("glcGetError", lib);
		bindFunc(glcIsContext)("glcIsContext", lib);
		bindFunc(glcCallbackFunc)("glcCallbackFunc", lib);
		bindFunc(glcDataPointer)("glcDataPointer", lib);
		bindFunc(glcDeleteGLObjects)("glcDeleteGLObjects", lib);
		bindFunc(glcDisable)("glcDisable", lib);
		bindFunc(glcEnable)("glcEnable", lib);
		bindFunc(glcGetCallbackFunc)("glcGetCallbackFunc", lib);
		bindFunc(glcGetListc)("glcGetListc", lib);
		bindFunc(glcGetListi)("glcGetListi", lib);
		bindFunc(glcGetPointer)("glcGetPointer", lib);
		bindFunc(glcGetc)("glcGetc", lib);
		bindFunc(glcGetf)("glcGetf", lib);
		bindFunc(glcGetfv)("glcGetfv", lib);
		bindFunc(glcGeti)("glcGeti", lib);
		bindFunc(glcIsEnabled)("glcIsEnabled", lib);
		bindFunc(glcStringType)("glcStringType", lib);
		bindFunc(glcAppendCatalog)("glcAppendCatalog", lib);
		bindFunc(glcGetMasterListc)("glcGetMasterListc", lib);
		bindFunc(glcGetMasterMap)("glcGetMasterMap", lib);
		bindFunc(glcGetMasterc)("glcGetMasterc", lib);
		bindFunc(glcGetMasteri)("glcGetMasteri", lib);
		bindFunc(glcPrependCatalog)("glcPrependCatalog", lib);
		bindFunc(glcRemoveCatalog)("glcRemoveCatalog", lib);
		bindFunc(glcAppendFont)("glcAppendFont", lib);
		bindFunc(glcDeleteFont)("glcDeleteFont", lib);
		bindFunc(glcFont)("glcFont", lib);
		bindFunc(glcFontFace)("glcFontFace", lib);
		bindFunc(glcFontMap)("glcFontMap", lib);
		bindFunc(glcGenFontID)("glcGenFontID", lib);
		bindFunc(glcGetFontFace)("glcGetFontFace", lib);
		bindFunc(glcGetFontListc)("glcGetFontListc", lib);
		bindFunc(glcGetFontMap)("glcGetFontMap", lib);
		bindFunc(glcGetFontc)("glcGetFontc", lib);
		bindFunc(glcGetFonti)("glcGetFonti", lib);
		bindFunc(glcIsFont)("glcIsFont", lib);
		bindFunc(glcNewFontFromFamily)("glcNewFontFromFamily", lib);
		bindFunc(glcNewFontFromMaster)("glcNewFontFromMaster", lib);
		bindFunc(glcLoadIdentity)("glcLoadIdentity", lib);
		bindFunc(glcLoadMatrix)("glcLoadMatrix", lib);
		bindFunc(glcMultMatrix)("glcMultMatrix", lib);
		bindFunc(glcRotate)("glcRotate", lib);
		bindFunc(glcScale)("glcScale", lib);
		bindFunc(glcRenderChar)("glcRenderChar", lib);
		bindFunc(glcRenderCountedString)("glcRenderCountedString", lib);
		bindFunc(glcRenderString)("glcRenderString", lib);
		bindFunc(glcRenderStyle)("glcRenderStyle", lib);
		bindFunc(glcReplacementCode)("glcReplacementCode", lib);
		bindFunc(glcResolution)("glcResolution", lib);
		bindFunc(glcGetCharMetric)("glcGetCharMetric", lib);
		bindFunc(glcGetMaxCharMetric)("glcGetMaxCharMetric", lib);
		bindFunc(glcGetStringCharMetric)("glcGetStringCharMetric", lib);
		bindFunc(glcGetStringMetric)("glcGetStringMetric", lib);
		bindFunc(glcMeasureCountedString)("glcMeasureCountedString", lib);
		bindFunc(glcMeasureString)("glcMeasureString", lib);
		bindFunc(glcPushMatrixQSO)("glcPushMatrixQSO", lib);
		bindFunc(glcPopMatrixQSO)("glcPopMatrixQSO", lib);
		bindFunc(glcPushAttribQSO)("glcPushAttribQSO", lib);
		bindFunc(glcPopAttribQSO)("glcPopAttribQSO", lib);	
	}
}
GenericLoader DerelictGLC;
static this() {
    DerelictGLC.setup(
        "glc32.dll",
        "libGLC.so",
        "",
        &load
    );
}

version(Windows)
{
    extern(Windows) typedef GLboolean function() GLCfunc;
}
else
{
    extern(C) typedef GLboolean function() GLCfunc;
}

alias void GLCchar;
alias GLint GLCenum;

enum
{
 GLC_NONE                                 = 0x0000,

 GLC_AUTO_FONT                            = 0x0010,
 GLC_GL_OBJECTS                           = 0x0011,
 GLC_MIPMAP                               = 0x0012,

 GLC_OP_glcUnmappedCode                   = 0x0020,

 GLC_BASELINE                             = 0x0030,
 GLC_BOUNDS                               = 0x0031,

 GLC_PARAMETER_ERROR                      = 0x0040,
 GLC_RESOURCE_ERROR                       = 0x0041,
 GLC_STATE_ERROR                          = 0x0042,

 GLC_CHAR_LIST                            = 0x0050,
 GLC_FACE_LIST                            = 0x0051,

 GLC_FAMILY                               = 0x0060,
 GLC_MASTER_FORMAT                        = 0x0061,
 GLC_VENDOR                               = 0x0062,
 GLC_VERSION                              = 0x0063,

 GLC_CHAR_COUNT                           = 0x0070,
 GLC_FACE_COUNT                           = 0x0071,
 GLC_IS_FIXED_PITCH                       = 0x0072,
 GLC_MAX_MAPPED_CODE                      = 0x0073,
 GLC_MIN_MAPPED_CODE                      = 0x0074,
 GLC_IS_OUTLINE                           = 0x0075,

 GLC_CATALOG_LIST                         = 0x0080,

 GLC_CURRENT_FONT_LIST                    = 0x0090,
 GLC_FONT_LIST                            = 0x0091,
 GLC_LIST_OBJECT_LIST                     = 0x0092,
 GLC_TEXTURE_OBJECT_LIST                  = 0x0093,

 GLC_DATA_POINTER                         = 0x00A0,

 GLC_EXTENSIONS                           = 0x00B0,
 GLC_RELEASE                              = 0x00B1,

 GLC_RESOLUTION                           = 0x00C0,

 GLC_BITMAP_MATRIX                        = 0x00D0,

 GLC_CATALOG_COUNT                        = 0x00E0,
 GLC_CURRENT_FONT_COUNT                   = 0x00E1,
 GLC_FONT_COUNT                           = 0x00E2,
 GLC_LIST_OBJECT_COUNT                    = 0x00E3,
 GLC_MASTER_COUNT                         = 0x00E4,
 GLC_MEASURED_CHAR_COUNT                  = 0x00E5,
 GLC_RENDER_STYLE                         = 0x00E6,
 GLC_REPLACEMENT_CODE                     = 0x00E7,
 GLC_STRING_TYPE                          = 0x00E8,
 GLC_TEXTURE_OBJECT_COUNT                 = 0x00E9,
 GLC_VERSION_MAJOR                        = 0x00EA,
 GLC_VERSION_MINOR                        = 0x00EB,

 GLC_BITMAP                               = 0x0100,
 GLC_LINE                                 = 0x0101,
 GLC_TEXTURE                              = 0x0102,
 GLC_TRIANGLE                             = 0x0103,

 GLC_UCS1                                 = 0x0110,
 GLC_UCS2                                 = 0x0111,
 GLC_UCS4                                 = 0x0112,

 GLC_SGI_ufm_typeface_handle              = 1,
 GLC_UFM_TYPEFACE_HANDLE_SGI              = 0x8001,
 GLC_UFM_TYPEFACE_HANDLE_COUNT_SGI        = 0x8003,
 GLC_SGI_full_name                        = 1,
 GLC_FULL_NAME_SGI                        = 0x8002,

 GLC_QSO_utf8                             = 1,
 GLC_UTF8_QSO                             = 0x8004,

 GLC_QSO_hinting                          = 1,
 GLC_HINTING_QSO                          = 0x8005,

 GLC_QSO_extrude                          = 1,
 GLC_EXTRUDE_QSO                          = 0x8006,

 GLC_QSO_kerning                          = 1,
 GLC_KERNING_QSO                          = 0x8007,

 GLC_QSO_matrix_stack                     = 1,
 GLC_MATRIX_STACK_DEPTH_QSO               = 0x8008,
 GLC_MAX_MATRIX_STACK_DEPTH_QSO           = 0x8009,
 GLC_STACK_OVERFLOW_QSO                   = 0x800A,
 GLC_STACK_UNDERFLOW_QSO                  = 0x800B,

 GLC_QSO_attrib_stack                     = 1,
 GLC_ENABLE_BIT_QSO                       = 0x00000001,
 GLC_RENDER_BIT_QSO                       = 0x00000002,
 GLC_STRING_BIT_QSO                       = 0x00000004,
 GLC_GL_ATTRIB_BIT_QSO                    = 0x00000008,
 GLC_ALL_ATTRIB_BITS_QSO                  = 0x0000FFFF,
 GLC_ATTRIB_STACK_DEPTH_QSO               = 0x800C,
 GLC_MAX_ATTRIB_STACK_DEPTH_QSO           = 0x800D
}

//==============================================================================
// DLL FUNCTIONS
//==============================================================================
private const char[] Funcs =
"
	typedef void function(GLint) pfglcContext;
	typedef void function(GLint) pfglcDeleteContext;
	typedef GLint function() pfglcGenContext;
	typedef GLint* function() pfglcGetAllContexts;
	typedef GLint function() pfglcGetCurrentContext;
	typedef GLCenum function() pfglcGetError;
	typedef GLboolean function(GLint) pfglcIsContext;	typedef void function(GLCenum, GLCfunc) pfglcCallbackFunc;
	typedef void function(GLvoid*) pfglcDataPointer;
	typedef void function() pfglcDeleteGLObjects;
	typedef void function(GLCenum) pfglcDisable;
	typedef void function(GLCenum) pfglcEnable;
	typedef GLCfunc function(GLCenum) pfglcGetCallbackFunc;
	typedef GLCchar* function(GLCenum, GLint) pfglcGetListc;
	typedef GLint function(GLCenum, GLint) pfglcGetListi;
	typedef GLvoid* function(GLCenum) pfglcGetPointer;
	typedef GLCchar* function(GLCenum) pfglcGetc;
	typedef GLfloat function(GLCenum) pfglcGetf;
	typedef GLfloat* function(GLCenum, GLfloat*) pfglcGetfv;
	typedef GLint function(GLCenum) pfglcGeti;
	typedef GLboolean function(GLCenum) pfglcIsEnabled;
	typedef void function(GLCenum) pfglcStringType;
	typedef void function(GLCchar*) pfglcAppendCatalog;
	typedef GLCchar* function(GLint, GLCenum, GLint) pfglcGetMasterListc;
	typedef GLCchar* function(GLint, GLint) pfglcGetMasterMap;
	typedef GLCchar* function(GLint, GLCenum) pfglcGetMasterc;
	typedef GLint function(GLint, GLCenum) pfglcGetMasteri;
	typedef void function(GLCchar*) pfglcPrependCatalog;
	typedef void function(GLint) pfglcRemoveCatalog;
	typedef void function(GLint) pfglcAppendFont;
	typedef void function(GLint) pfglcDeleteFont;
	typedef void function(GLint) pfglcFont;
	typedef GLboolean function(GLint, GLCchar*) pfglcFontFace;
	typedef void function(GLint, GLint, GLCchar*) pfglcFontMap;
	typedef GLint function() pfglcGenFontID;
	typedef GLCchar* function(GLint) pfglcGetFontFace;
	typedef GLCchar* function(GLint, GLCenum, GLint) pfglcGetFontListc;
	typedef GLCchar* function(GLint, GLint) pfglcGetFontMap;
	typedef GLCchar* function(GLint, GLCenum) pfglcGetFontc;
	typedef GLint function(GLint, GLCenum) pfglcGetFonti;
	typedef GLboolean function(GLint) pfglcIsFont;
	typedef GLint function(GLint, GLCchar*) pfglcNewFontFromFamily;
	typedef GLint function(GLint, GLint) pfglcNewFontFromMaster;
	typedef void function() pfglcLoadIdentity;
	typedef void function(GLfloat*) pfglcLoadMatrix;
	typedef void function(GLfloat*) pfglcMultMatrix;
	typedef void function(GLfloat) pfglcRotate;
	typedef void function(GLfloat, GLfloat) pfglcScale;
	typedef void function(GLint) pfglcRenderChar;
	typedef void function(GLint, GLCchar*) pfglcRenderCountedString;
	typedef void function(GLCchar*) pfglcRenderString;
	typedef void function(GLCenum) pfglcRenderStyle;
	typedef void function(GLint) pfglcReplacementCode;
	typedef void function(GLfloat) pfglcResolution;
	typedef GLfloat* function(GLint, GLCenum, GLfloat*) pfglcGetCharMetric;
	typedef GLfloat* function(GLCenum, GLfloat *) pfglcGetMaxCharMetric;
	typedef GLfloat* function(GLint, GLCenum, GLfloat*) pfglcGetStringCharMetric;
	typedef GLfloat* function(GLCenum, GLfloat*) pfglcGetStringMetric;
	typedef GLint function(GLboolean, GLint, GLCchar*) pfglcMeasureCountedString;
	typedef GLint function(GLboolean, GLCchar*) pfglcMeasureString;
	typedef void function() pfglcPushMatrixQSO;
	typedef void function() pfglcPopMatrixQSO;
	typedef void function(GLbitfield) pfglcPushAttribQSO;
	typedef void function() pfglcPopAttribQSO;
";

version(Windows)
{
	extern(Windows): mixin(Funcs);
}
else
{
	extern(C): mixin(Funcs);
}

pfglcContext glcContext;
pfglcDeleteContext glcDeleteContext;
pfglcGenContext glcGenContext;
pfglcGetAllContexts glcGetAllContexts;
pfglcGetCurrentContext glcGetCurrentContext;
pfglcGetError glcGetError;
pfglcIsContext glcIsContext;pfglcCallbackFunc glcCallbackFunc;
pfglcDataPointer glcDataPointer;
pfglcDeleteGLObjects glcDeleteGLObjects;
pfglcDisable glcDisable;
pfglcEnable glcEnable;
pfglcGetCallbackFunc glcGetCallbackFunc;
pfglcGetListc glcGetListc;
pfglcGetListi glcGetListi;
pfglcGetPointer glcGetPointer;
pfglcGetc glcGetc;
pfglcGetf glcGetf;
pfglcGetfv glcGetfv;
pfglcGeti glcGeti;
pfglcIsEnabled glcIsEnabled;
pfglcStringType glcStringType;
pfglcAppendCatalog glcAppendCatalog;
pfglcGetMasterListc glcGetMasterListc;
pfglcGetMasterMap glcGetMasterMap;
pfglcGetMasterc glcGetMasterc;
pfglcGetMasteri glcGetMasteri;
pfglcPrependCatalog glcPrependCatalog;
pfglcRemoveCatalog glcRemoveCatalog;
pfglcAppendFont glcAppendFont;
pfglcDeleteFont glcDeleteFont;
pfglcFont glcFont;
pfglcFontFace glcFontFace;
pfglcFontMap glcFontMap;
pfglcGenFontID glcGenFontID;
pfglcGenFontID glcGetFontFace;
pfglcGetFontListc glcGetFontListc;
pfglcGetFontMap glcGetFontMap;
pfglcGetFontc glcGetFontc;  
pfglcGetFonti glcGetFonti;
pfglcGetFonti glcIsFont;
pfglcNewFontFromFamily glcNewFontFromFamily;
pfglcNewFontFromMaster glcNewFontFromMaster;
pfglcLoadIdentity glcLoadIdentity;
pfglcLoadMatrix glcLoadMatrix;
pfglcMultMatrix glcMultMatrix;
pfglcRotate glcRotate;
pfglcScale glcScale;
pfglcRenderChar glcRenderChar;
pfglcRenderCountedString glcRenderCountedString;
pfglcRenderString glcRenderString;
pfglcRenderStyle glcRenderStyle;
pfglcReplacementCode glcReplacementCode;
pfglcResolution glcResolution;
pfglcGetCharMetric glcGetCharMetric;
pfglcGetMaxCharMetric glcGetMaxCharMetric;
pfglcGetStringCharMetric glcGetStringCharMetric;
pfglcGetStringMetric glcGetStringMetric;
pfglcMeasureCountedString glcMeasureCountedString;
pfglcMeasureString glcMeasureString;
pfglcPushMatrixQSO glcPushMatrixQSO;
pfglcPopMatrixQSO glcPopMatrixQSO;
pfglcPushAttribQSO glcPushAttribQSO;
pfglcPopAttribQSO glcPopAttribQSO;

